package org.axed.user.client.axessory;

import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Widget;
import org.axed.user.client.AxedArea;
import org.axed.user.client.AxedEvent;
import org.axed.user.client.AxedListener;
import org.axed.user.client.DOM;
import org.timepedia.exporter.client.Exportable;

/**
 * The horizontal Positionbar resides above an AxedArea with fixed fonts.
 * It shows the character columns and the cursor position with them.
 *
 * With non-fixed fonts, it doesn't make much sense.
 *
 * @gwt.exportPackage axed
 * @gwt.export
 */
public class HPositionBar extends Widget implements AxedListener, Exportable {
	Element bar;
	int width;
	int height = 15;
	int colWidth; 

	/**
	 * How far did the bar get the columns drawn? (this matters when the edit box is scrolling)
	 */
	int colsDrawn = 0; 
	int scrollPos = 0;

	Element colCaret1;
	Element colCaret2;

	/**
	 * The AxedArea this belongs to.
	 */
	AxedArea axed;

	
	/**
	 * Constructor 
	 *
	 * @param axed      the axedWidget to belong to.
	 * @param setDiv    the div to use, if null it will be created.
	 * @param setWidth  the width
	 * @param colWidth  the with of a column
	 */
	public HPositionBar(AxedArea axed, Element setDiv) {
		super();

		this.axed = axed;
		colWidth = axed.document.getColWidth();
		
		if (setDiv == null) {
			bar = DOM.createDiv();
		} else {
			bar = setDiv;
		}
		DOM.setStyleAttribute(bar, "borderLeft", "1px solid");
		DOM.setStyleAttribute(bar, "borderRight", "1px solid");
		DOM.setStyleAttribute(bar, "width", (axed.setWidth - 1) + "px");
		DOM.setStyleAttribute(bar, "height", (height) + "px");
		DOM.setStyleAttribute(bar, "position", "relative");
		DOM.setStyleAttribute(bar, "background", "#CCCCCC");
		DOM.setStyleAttribute(bar, "margin", "0px");
		DOM.setStyleAttribute(bar, "padding", "0px");
		DOM.setStyleAttribute(bar, "overflow", "hidden");
		setElement(bar);		

		colCaret1 = DOM.createDiv();
		DOM.setStyleAttribute(colCaret1, "fontSize", "0");   // Workarond IE 6.0 Bug
		DOM.setStyleAttribute(colCaret1, "overflow", "hidden");   // Workarond IE 6.0 Bug
		DOM.setStyleAttribute(colCaret1, "position", "absolute");
		DOM.setStyleAttribute(colCaret1, "left", "-3px");
		DOM.setStyleAttribute(colCaret1, "top", "0px");
		DOM.setStyleAttribute(colCaret1, "width", "5px");
 		DOM.setStyleAttribute(colCaret1, "margin", "0px");
 		DOM.setStyleAttribute(colCaret1, "height", "1px");
		DOM.setStyleAttribute(colCaret1, "background", "black");
		DOM.setStyleAttribute(colCaret1, "padding", "0px");

		colCaret2 = DOM.createDiv();
		DOM.setStyleAttribute(colCaret2, "fontSize", "0");   // Workarond IE 6.0 Bug
		DOM.setStyleAttribute(colCaret2, "overflow", "hidden");   // Workarond IE 6.0 Bug
		DOM.setStyleAttribute(colCaret2, "position", "absolute");
		DOM.setStyleAttribute(colCaret2, "left", "0px");
		DOM.setStyleAttribute(colCaret2, "top", "0px");
		DOM.setStyleAttribute(colCaret2, "width", "1px");
		DOM.setStyleAttribute(colCaret2, "height", "3px");
		DOM.setStyleAttribute(colCaret2, "background", "black");
		DOM.setStyleAttribute(colCaret2, "padding", "0px");

		DOM.appendChild(bar,colCaret1);
		DOM.appendChild(bar,colCaret2);
		width = DOM.getElementPropertyInt(bar, "offsetWidth");
	}

	/**
 	 * Returns the HPositionBar DOM-Element.
 	 */
	public Element getBarElement() {
		return bar;
	}
	
	/**
 	 * Moves the Column caret to the position X.
 	 */
	public void moveCaret() {
		int x = axed.getCaret().getCoords().left;

		DOM.setStyleAttribute(colCaret1, "left", (x - axed.document.getColWidth() / 2) + "px");
		DOM.setStyleAttribute(colCaret2, "left", x + "px");
	}

	/**
	 * Called from AxedArea on events.
	 * @gwt.noexport
	 */
	public void onAxedEvent(AxedEvent event) {
		switch (event.type) {
		case AxedEvent.MOVE_CURSOR : 
		case AxedEvent.REFRESH : 
			moveCaret();
			break;
		case AxedEvent.FONT_SIZE_CHANGED :
			changedFontSize();
			break;
		case AxedEvent.SCROLL :
			scroll();
			break;
		}
	}

	/**
	 * Should be called, when been resized.
	 */
	public void resized() {
		width = DOM.getElementPropertyInt(bar, "offsetWidth");
		if (colWidth > 0) {
			expandBar(width / colWidth);
		}
	}

//privates:
	private void expandBar(int cols) {
		int j;
		Element e;

		for (int i = colsDrawn; i < cols; i++) {
			e = DOM.createDiv();
			j = 5;
			if (i % 5 == 0) {
				j = 7;
			}
			DOM.setStyleAttribute(e, "fontSize", "0");   // Workarond IE 6.0 Bug
			DOM.setStyleAttribute(e, "position", "absolute");
			DOM.setStyleAttribute(e, "left", (i * colWidth + AxedArea.borderLeft) + "px");
			DOM.setStyleAttribute(e, "top", (height - j + 2) + "px");
			DOM.setStyleAttribute(e, "height", j + "px");
			DOM.setStyleAttribute(e, "width", "1px");
			DOM.setStyleAttribute(e, "background", "black");
			DOM.appendChild(bar, e);
		}
		for (int i = colsDrawn + (10 - (colsDrawn % 10)); i <= cols; i+=10) {
			e = DOM.createSpan();
			DOM.setStyleAttribute(e, "position", "absolute");
			DOM.setStyleAttribute(e, "top", 0 + "px");
			//DOM.setStyleAttribute(e, "fontFamily", "monospace");
			DOM.setStyleAttribute(e, "fontSize", "0.8em");
			DOM.setInnerText(e, "" + i);
			DOM.appendChild(bar, e);
			DOM.setStyleAttribute(e, "top",  ((height - DOM.getElementPropertyInt(e,"offsetHeight")) / 2 - 1) + "px");
			int middlepos = 0;
			if (i != 0) {
				middlepos = DOM.getElementPropertyInt(e,"offsetWidth") / 2;
			}
			DOM.setStyleAttribute(e, "left", (i * colWidth + AxedArea.borderLeft - middlepos) + "px");
		}
		colsDrawn = cols;
	}

	/**
	 * Handles fontsize changes
	 */
	private void changedFontSize() {
		height = axed.document.getLineHeight();
		colWidth = axed.document.getColWidth();
		rebuildBar();
		moveCaret();
	}

	/**
	 * Completly create the bar from new.
	 * For example after a font resize. 
	 */
	private void rebuildBar() {
		DOM.removeChild(bar, colCaret1);
		DOM.removeChild(bar, colCaret2);
		DOM.setInnerText(bar,"");

		DOM.setStyleAttribute(bar, "height", (height + 2) + "px");
		colsDrawn = 0;
		expandBar((width + AxedArea.borderLeft + AxedArea.borderRight) / colWidth);
		DOM.setStyleAttribute(colCaret1, "width",  (colWidth) + "px");
		DOM.setStyleAttribute(colCaret2, "height", (height / 2 - 2) + "px");

		DOM.appendChild(bar,colCaret1);
		DOM.appendChild(bar,colCaret2);
	}

	/**
	 * Scrolls the bar to match the assigned axed widget. 
	 */
	private void scroll() {
		int sl = axed.getScrollLeft();
		if (sl == scrollPos) {
			return;
		}
		int colsNeeded = (sl + width + AxedArea.borderLeft + AxedArea.borderRight) / colWidth;
		if (colsNeeded > colsDrawn) {
			expandBar(colsNeeded);
		}
		DOM.setElementPropertyInt(bar, "scrollLeft", sl);
		scrollPos = sl;
	}
}
